/* Copyright  2009
   @Author
   Richard Changde Yin            e-mail yinchangde@hotmail.com

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/**
 * @filename: process.h
 */

#ifndef __PROCESS_H__
#define __PROCESS_H__

#include <global.h>

#include <os.h>
#include <error.h>
#include <mutex.h>
#include <transaction.h>
#include <util.h>

#include <read-config.h>

class ProcInfo
{
public:

    ProcInfo():pid_(-1),numThreads_(-1) {}

    pid_t pid_;

    int numThreads_;

};

struct ThreadTrans{

    pid_t       pid_;

    pthread_t thrid_;

    Transaction *trans_;

    ThreadTrans():pid_(-1), thrid_(0), trans_ (NULL) {}

    inline void init()   { pid_=-1; thrid_ =0; trans_ = NULL; }

    inline void print();
};


class ThreadInfo
{
public:

    pid_t pid_;

    pthread_t thrid_;
    //list of thread specific transactions
    ThreadTrans thrTrans_ [MAX_THREADS_PER_PROCESS];

    Mutex *want_mtx;  //single mutex which we are waiting for.

    Mutex *has_mtx [MAX_MUTEX_PER_THREAD];   //list of mutexes held

    inline void init()
    {
       ///PID
        pid_ = 0;
        /// pthread id.
        thrid_ =0;
        /// mutex
        want_mtx = NULL;

        for (int i =0; i <MAX_MUTEX_PER_THREAD; i++) has_mtx [i] = NULL;
       /// init the struct of ThreadTrans Array.
        for (int i =0; i <Conf::config.getMaxProcs(); i++)  thrTrans_[i].init();
    }

    inline void init(pid_t _pid,pthread_t _thread);

    inline void reset()
    {
      init();
    }

    void print();

};
class Database;

class ProcessManager
{
public:
    static int noThreads;

    static Mutex prcMgr_mutex;

    static caddr_t sysAddr;

    static caddr_t usrAddr;
    ///The global static Database pointer
    static Database *systemDatabase;

    static BackEnd::List<void> hasLockList;

    ThreadInfo *thrInfo;

    ProcessManager() { }

    BackEnd::DbRetVal registerThread();

    BackEnd::DbRetVal deregisterThread(int slot);

    static BackEnd::DbRetVal addMutex(Mutex *mutex, int pslot);
    static BackEnd::DbRetVal removeMutex(Mutex *mutex, int pslot);

    static BackEnd::DbRetVal setThreadTransaction(Transaction *trans,int pslot);
    static Transaction*  getThreadTransaction(int pslot);
    static Transaction** getThreadTransAddr(int pslot);

    void printUsageStatistics();
    void printDebugInfo();

    int procSlot;
    inline int getProcSlot() { return procSlot; }

    bool isAnyOneRegistered();
};

#endif //__PROCESS_H__
